package com.googlecode.alogwe.sprockit.engine;

import java.util.LinkedList;

import com.googlecode.alogwe.sprockit.js.JSScript;

public class ScriptQueue {

	private static ScriptQueue		instance	= null;
	private LinkedList<JSScript>	list;
	private volatile boolean		isEmpty;

	/**
	 * Private Constructor for singleton
	 */
	private ScriptQueue() {
		this.list = new LinkedList<JSScript>();
		this.isEmpty = true; // Initial state is empty
		ScriptQueue.instance = this;
	}

	/**
	 * Provides access to the singleton instance of this class.
	 * 
	 * @return The singleton instance of ScriptQueue.
	 */
	public static ScriptQueue getInstance() {
		if (ScriptQueue.instance == null) {
			ScriptQueue.instance = new ScriptQueue();
		}
		return ScriptQueue.instance;
	}

	/**
	 * Adds a new script to the list only if the list is empty. Otherwise this
	 * method will block until the current JSScript in the list is consumed.
	 * <p>
	 * <b>TODO</b> Rewrite behavior to allow a list length of greater than one
	 * JSScript otherwise there's no point in using a Collection type.
	 * 
	 * @param script
	 *            A JSScript instance
	 * @return A boolean value whether or not the script instance was
	 *         successfully added to the LinkedList.
	 * @throws InterruptedException
	 */
	public boolean put(JSScript script) throws InterruptedException {
		synchronized (list) {
			while (!isEmpty) { // <-- Guarded
				list.wait();
			}
			boolean result = list.add(script);
			this.isEmpty = false;
			list.notifyAll();
			return result;
		}
	}

	/**
	 * Gets a JSScript instance from the list if the list is not empty.
	 * Otherwise this method will block until a JSScript is added to the list
	 * with put().
	 * <p>
	 * <b>TODO</b> Rewrite behavior to allow a list length of greater than one
	 * JSScript otherwise there's no point in using a Collection type.
	 * 
	 * @return A JSScript instance.
	 * @throws InterruptedException
	 */
	public JSScript get() throws InterruptedException {
		synchronized (list) {
			while (isEmpty) { // <-- Guarded
				list.wait();
			}
			JSScript result = list.removeFirst();
			this.isEmpty = true;
			list.notifyAll();
			return result;
		}
	}

	// Used for debugging purposes
	// private void print(String s) {
	// Thread t = Thread.currentThread();
	// String threadInfo = "Thread [" + t.getId() + "] : ";
	// System.out.println(threadInfo + s);
	// }
}
